﻿"use strict";

const roomMgr = require("../roomMgr");
const clientMgr = require("../clientMgr");
const socket = require('../../base_net/socket');
const crypto = require('../../utils/crypto');
const db = require("../../utils/db");
const logger = require("../../utils/logger");
var utils = require("../../utils/utils");

var games = {};
var gameSeatsOfUsers = {};
//超过半小时自动解散
var  kickList = {};

var DXOptionalOperate = {
    EAT_TOUCH_BELT: 0,
    EAT_TOUCH: 1,
    BELT: 2,
    EAT: 3,
    EAT_BELT: 4,
    REVERSE_BELT: 5,
};

var DXOperate = {
    EAT: 0,
    TOUCH: 1,
    BELT: 2,
    WAIVE: 3,
    REVERSE_BELT: 4,
    NO_BELT: 5,
    ONLY_EAT: 6,
};

var CARD_TYPE = [
    "2Jr", "2Qr", "2Xm", "2Xr", "3Qm", "4Qm", "4Qr", "5Qr", "6Qm", "6Qr", 
    "7Qm", "7Qr", "8Qb", "8Qm", "8Qr", "9Qb", "9Qm", "9Qr", "13b", "22b",
    "23m", "24m", "24r", "25r", "26m", "26r", "27m", "27r", "28b", "28m",
    "28r", "44b", "44m", "44r", "45r", "55r", "66b", "66r", "77b", "77r",
    "88b", "88r", "99r", "b3r4", "JJr", "JQr", "QQr", "r4b8", "r4J", "r4X",
    "r47", "r49", "XQm", "XQr", "XXb", "XXr"
];

exports.setReady = function(userId,value){
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var s = roomInfo.seats[seatIndex];
    logger.game_log("检测赔底", roomInfo.settle);
    if (hasCompensate(roomInfo) && !isLastRoundPlayer(userId, roomInfo)) {
        logger.game_log("有赔底，无法准备");
        s.sit = 0;
        clientMgr.sendMsg(userId,socket.resp.user_sit,{userId:userId,sit:false});
        clientMgr.sendMsg(userId,socket.resp.user_ready,{userId:userId,ready:false});
        return;
    }
    s.ready = value?true:false;
    clientMgr.broadcastInRoom(socket.resp.user_ready,{userId:userId,ready:value},userId,true);
    if((kickList[userId] || kickList[userId] >= 0) && s.sit == 1){
        delete kickList[userId];
    }

    var game = games[ roomId ];
    if( game == null ) {
        var count = 0;
        for( var i = 0; i < roomInfo.seats.length; ++i ) {
            var s = roomInfo.seats[ i ];
            if( s && s.userId > 0 && s.sit == 1){
                if(!s.ready){
                    if(roomInfo.conf.maxGames > 0)return;
                    continue;
                }
                count ++;
            }
        }
        if(count <= 1)return;
        if(roomInfo.numOfGames == 0){
            roomMgr.setStart( roomId );
        }
        //人数已经到齐了，并且都准备好了，则开始新的一局
        logger.game_log("启动钓蟹游戏");
        begin( roomId );
    }
}

exports.gameBegin = function(roomInfo){
    var roomId = roomInfo.roomId;
    if(roomInfo.numOfGames == 0){
        roomMgr.setStart( roomId );
    }
    logger.game_log("启动钓蟹游戏");
    //人数已经到齐了，并且都准备好了，则开始新的一局
    var game = games[ roomId ];
    if( game == null ) {
        begin(roomId);
    }
}
exports.sitDown = function(userId,value){
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }

    var s = roomInfo.seats[seatIndex];
    s.sit = value == false?0:1;
    // getNiuniu2(userId);
    clientMgr.broadcastInRoom(socket.resp.user_sit,{userId:userId,sit:s.sit},userId,true);

    if(roomInfo.numOfGames > 0 || roomInfo.conf.maxGames <= 0){
        delete kickList[userId];
    }
}
exports.syncInfo = function(userId){
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null || roomInfo.numOfGames == 0){
        return;
    }

    var game = games[ roomId ];
    var data = {};
    if( game != null ) {
        var ddd = game.gameSeats[game.button];

        data = {
            state : game.state,
            gameState:roomInfo.gameState,
            button : ddd != null?ddd.userId:0,
        };
        data.fundPool = game.fundPool;
        data.beltNowCost = game.beltNowCost;
        if (game.turnGamber != null) {
            data.gamber = game.gameSeats[game.turnGamber].userId;
            data.operates = getOptionalOperate(game, game.turnGamber);
        }
        data.seats = [];

        for(var i = 0; i < roomInfo.conf.roomNum; ++i) {
            var rs = roomInfo.seats[i];
            var sd = game.gameSeats[i];
            if( !sd ) continue;

            if(sd.userId == userId){
                rs.exitAfterEnd = false;
            }

            var s = {
                userId:sd.userId,
                scoreBetting : sd.scoreBetting,
                score: sd.scoreBetting,
                hasBetting : sd.hasBetting,
                sit : sd.sit,
                ready : rs.ready,
            }

            var holds = null;
            if(data.state == 5){
                holds = sd.holds;
                var niu = calculate(holds);
                s.niu = niu;
                s.cardType = getCardType(holds);
            }
            else{
                if(sd.sit == 1 && rs.ready && sd.userId == userId){
                    holds = utils.clone(sd.holds);
                    // holds[holds.length-1] = -1;
                }
            }
            s.holds = holds;
            data.seats.push(s);
        }
    }
    else{
        data = {
            state : 0,
            gameState:roomInfo.gameState,
        };
        data.seats = [];
        for(var i = 0; i < roomInfo.conf.roomNum; ++i) {
            var sd = roomInfo.seats[i];
            if( sd.userId <= 0 ) continue;

            var s = {
                userId:sd.userId,
                ready : sd.ready,
                sit : sd.sit,
            }
            data.seats.push(s);
        }
    }
    data.record = roomInfo.allRecord;
    //同步整个信息给客户端
    clientMgr.sendMsg(userId,socket.resp.game_sync,data);
}

exports.get_tick_time = function(userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return null;
    }
    if(kickList[userId] == null || kickList[userId] <= 0) {
        var seatIndex = roomMgr.getUserIndex(userId);
        if (seatIndex == null || seatIndex == 0) {
            return kickList;
        }
        var s = roomInfo.seats[seatIndex];
        if (s.sit == 0 || (s.ready == 0 && roomInfo.conf.maxGames > 0)) {
            kickList[userId] = 120;
        }
        /*else if (s.ready == 0) {
            kickList[userId] = 120;
        }*/
    }
    return kickList;
}
// exports.setNiuniu = function(userId) {
//     db.niuniu_permission(userId,function (code) {
//         if(code == 2)return;
//         if(code == 1){
//             clientMgr.sendMsg(userId, socket.resp.niuniu_resp,{code:1});
//             return;
//         }
//         var roomId = roomMgr.getUserRoomId(userId);
//         if(roomId == null){
//             return;
//         }
//         var roomInfo = roomMgr.getRoom(roomId);
//         if(roomInfo == null){
//             return;
//         }
//         var seatIndex = roomMgr.getUserIndex(userId);
//         if(seatIndex == null){
//             return;
//         }
//         var s = roomInfo.seats[seatIndex];
//         s.setNiuniu = true;
//         clientMgr.sendMsg(userId, socket.resp.niuniu_resp,{code:0});
//     })
// }

// function getNiuniu2(userId) {
//     db.getNiuniu2(userId,function (rate) {
//         var roomId = roomMgr.getUserRoomId(userId);
//         if(roomId == null){
//             return;
//         }
//         var roomInfo = roomMgr.getRoom(roomId);
//         if(roomInfo == null){
//             return;
//         }
//         var seatIndex = roomMgr.getUserIndex(userId);
//         if(seatIndex == null){
//             return;
//         }
//         var s = roomInfo.seats[seatIndex];
//         s.setNiuniu2 = rate;
//     })
// }
exports.exitAfterEnd = function (roomInfo,seatIndex){
    // if(roomInfo.owner == "999999"){
        var game = games[ roomInfo.roomId ];
        logger.game_log("exitAfterEnd", game == null);
        if( game == null ) {
            return false;
        }
        else{
            roomInfo.seats[seatIndex].exitAfterEnd = true;
            return true;
        }
    // }
    return true;
}
function clearExit(roomInfo) {
    if (roomInfo == null) return;
    var roomId = roomInfo.roomId;
    for(var i = 0; i < roomInfo.seats.length; ++i) {
        var rs = roomInfo.seats[i];
        if(rs.exitAfterEnd) {// || clientMgr.isOnline(rs.userId) == false){
            if (rs.exitAfterEnd && roomMgr.isCreator(roomId, rs.userId)) {
                clientMgr.broadcastInRoom(socket.resp.dispress,"dispress",rs.userId,false);
                clientMgr.kickAllInRoom(roomId);
                roomMgr.destroy(roomId);
                return;
            }
            rs.exitAfterEnd = false;
            clientMgr.sendMsg(rs.userId,socket.resp.exit_result,rs.userId);
            //通知其它玩家，有人退出了房间
            clientMgr.broadcastInRoom(socket.resp.exit_notify,rs.userId,rs.userId,false);

            roomMgr.exitRoom(rs.userId);
        }
    }
}
//开始新的一局
function begin(roomId) {
    var state = {
        idle : 0,
        // qiangzhuang : 1,
        dingzhuang : 2,
        xiazhu : 3,
        cuopai : 4,
        bipai : 5,
    };

    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null || games[roomId] != null){
        return;
    }

    clearExit(roomInfo);

    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null || games[roomId] != null){
        return;
    }

    roomMgr.payGameCost(roomId);

    var seats = roomInfo.seats;

    logger.game_log("房间信息", roomInfo.conf);
    var game = {
        conf:roomInfo.conf,
        roomInfo:roomInfo,
        allState : state,

        // qiangzhuangTime : 6,
        dingzhuangTime : 5,
        xiazhuTime : 30,
        cuopaiTime : 10,
        liangpaiTime  : 4,
        nextGameTime : 15,

        allCards : [],
        currentIndex:0,
        gameSeats:[],

        // isNiuniu : false,
        button: 0,
        state:0,
        eatNoRub:false,

        isReverseBelt: roomInfo.conf.isReverseBelt,   // 头家反带
        isOnlyEat:  roomInfo.conf.isOnlyEat,  // 头家闷吃
        fundPool: roomInfo.fundPool || 0,
        bankerOnlyEat: false,

        actionList:[],
    };
    if (game.fundPool == 0) {
        roomInfo.numOfGames++;
        if (roomInfo.conf.maxGames > 0 && roomInfo.numOfGames > roomInfo.conf.maxGames) {
            roomInfo.numOfGames = roomInfo.conf.maxGames;
        }
    }
    db.update_numOfGames(roomId,roomInfo.numOfGames);

    for(var i = 0; i < game.conf.roomNum; ++i) {
        if(seats[i].userId <= 0)continue;
        if(seats[i].sit == 0)continue;
        var data = game.gameSeats[i] = {};
        data.game = game;		//循环引用
        data.seatIndex = i;

        data.sit = seats[i].sit;
        data.userId = seats[i].userId;
        //持有的牌
        data.holds = [];

        data.score = 0;
        //抢庄倍数
        // data.hasQiang = false;
        // data.score1 = 0;
        //下注倍数
        data.hasXia = false;
        data.scoreBetting = 0;
        data.scoreReverse = 0;
        data.eliminate = false;
        data.hasLiang = false;
        data.hasBetting = false;
        data.hasRub = false;
        data.compensate = 0;    // 赔底

        // data.setNiuniu = seats[i].setNiuniu;
        // data.setNiuniu2 = seats[i].setNiuniu2;
        gameSeatsOfUsers[data.userId] = data;
    }

    var allHolds = [];

    // 只有一个人就结束游戏
    var count = 0;
    for(var i = 0; i < seats.length; ++i) {
        if (!game.gameSeats[i]) continue;
        //开局时，通知前端必要的数据
        var s = seats[i];
        if(s && s.userId > 0 && s.sit == 1){
            if (!s.ready) {
                return;
            }
            count += 1;
        }
    }
    logger.game_log("目前在坐的有", count, "人");
    if(count <= 1){
        if(roomInfo.owner != "999999"){
            // doGameOver2(game,roomId,true);
        }
        return;
    }
    updateFundPool(game, roomInfo, count);
    game.beltNowCost = game.fundPool;

    roomInfo.gameState = "playing";
    clientMgr.broadcastInRoom2(socket.resp.game_state,{state:roomInfo.gameState},roomId);

    games[roomId] = game;
    //洗牌
    shuffle(game);
    //发牌
    deal(game);
    // createNiuniu2(game);
    // createNiuniu(game);

    roomInfo.lastRoundPlayers = [];

    for(var i = 0; i < seats.length; ++i) {
        if (!game.gameSeats[i]) continue;
        //开局时，通知前端必要的数据
        var s = seats[i];
        //通知游戏开始
        clientMgr.sendMsg(s.userId, socket.resp.game_begin);
        //通知玩家手牌
        //var holds = utils.clone(game.gameSeats[i].holds);
        //holds[holds.length-1] = -1;
        //var data = {userId:s.userId,holds:holds};
        //clientMgr.sendMsg(s.userId, socket.resp.game_holds, [data]);
        game.gameSeats[i].cardType = getCardType(game.gameSeats[i].holds);
        allHolds.push({userId:s.userId,holds:game.gameSeats[i].holds,sit:s.sit,cardType:game.gameSeats[i].cardType});
        //通知还剩多少局
        clientMgr.sendMsg(s.userId, socket.resp.game_num, roomInfo.numOfGames);
        // 更新权限
        updatePermission(s.userId);
        roomInfo.lastRoundPlayers.push(s.userId);
    }
    for(var i = 0; i < seats.length; ++i) {
        if (!game.gameSeats[i]) continue;
        var s = seats[i];
        var allHolds2 = utils.clone(allHolds);
        for(var j=0;j<allHolds2.length;j++){
            var holds = allHolds2[j].holds;
            if(s.sit == 1 && s.userId == allHolds2[j].userId){
                // holds[holds.length-1] = -1;
            }
            else{
                allHolds2[j].holds = null;
            }
        }
        clientMgr.sendMsg(s.userId, socket.resp.game_holds, allHolds2);
    }
    recordGameAction(game,socket.resp.game_begin);
    recordGameAction(game,socket.resp.game_holds,allHolds);
    recordGameAction(game,socket.resp.game_num,roomInfo.numOfGames);

    // game.state = game.allState.qiangzhuang;
    // clientMgr.broadcastInRoom2(socket.resp.qiangzhuang_all,{time:game.qiangzhuangTime},game.roomInfo.roomId,true);
    // recordGameAction(game,socket.resp.qiangzhuang_all,{time:game.qiangzhuangTime});
    setBanker(game);
    // game.timeId1 = setTimeout(function () {
    //     dingzhuang(game);
    // },game.qiangzhuangTime * 1000);
};

function hasCompensate(roomInfo) {
    for(var i = 0; i < roomInfo.seats.length; ++i){
        var rs = roomInfo.seats[i];
        if (rs.compensate) {
            logger.game_log("有赔底", rs.userId);
            return true;
        }
    }
    logger.game_log("没有赔底");
    return false;
}

function isLastRoundPlayer(userId, roomInfo) {
    if (!roomInfo.lastRoundPlayers || roomInfo.lastRoundPlayers.length == 0) {
        return true;
    } else {
        return roomInfo.lastRoundPlayers.indexOf(userId) >= 0;
    }
}

function updateFundPool(game, roomInfo, count) {
    // 赔底
    var results = [];
    for(var i = 0; i < roomInfo.seats.length; ++i){
        var rs = roomInfo.seats[i];
        var sd = game.gameSeats[i];
        if( sd == null || sd.sit == 0 || sd.userId <= 0 || !rs.ready) continue;
        if (!rs.compensate) continue;

        game.fundPool += rs.compensate;
        rs.coins -= rs.compensate;
        rs.score -= rs.compensate;

        var userRT = {
            userId:sd.userId,
            area : rs.area,
            coins:rs.coins,
            score:-rs.compensate,
        };
        db.rate_coins(userRT);

        results.push({
            userId:sd.userId,
            coins:rs.coins,
            score:-rs.compensate,
        });
        delete rs.compensate;
    }
    game.bankerOnlyEat = game.fundPool == 0;
    if (game.fundPool < count * game.conf.difen) {
        game.fundPool += count * game.conf.difen;

		for(var i = 0; i < roomInfo.seats.length; ++i){
			var rs = roomInfo.seats[i];
			var sd = game.gameSeats[i];
			if( sd == null || sd.sit == 0 || sd.userId <= 0 || !rs.ready) continue;

			rs.coins -= game.conf.difen;
            rs.score -= game.conf.difen;

			var userRT = {
				userId:sd.userId,
                area : rs.area,
                coins:rs.coins,
                score:-game.conf.difen,
			};
            db.rate_coins(userRT);

            results.push({
				userId:sd.userId,
                coins:rs.coins,
                score:-game.conf.difen,
            });
		}
        
    }
    if (results) {
		for(var i = 0; i < roomInfo.seats.length; ++i){
			var rs = roomInfo.seats[i];
			var sd = game.gameSeats[i];
			if( sd == null || sd.userId <= 0) continue;
            clientMgr.sendMsg(rs.userId,socket.resp.dizhu_cost,{results:results,fundPool:game.fundPool});
            // clientMgr.broadcastInRoom2(socket.resp.dizhu_cost,{results:results,fundPool:game.fundPool},roomId);
        }
    }
}

function setBanker(game){
    var indexArr = [];
    var userArr = [];
    for (var i=0;i<game.gameSeats.length;i++){
        var seatData = game.gameSeats[i];
        if(!seatData || seatData.sit == 0)continue;
        if(seatData.userId > 0){
            indexArr.push(i);
            userArr.push(seatData.userId);
        }
    }
    var random = Math.floor(Math.random()*indexArr.length);
    game.button = indexArr[random];
    var banker = game.gameSeats[game.button];   // 庄家
    game.state = game.allState.dingzhuang;
    clientMgr.broadcastInRoom2(socket.resp.dingzhuang_all,{time:game.dingzhuangTime,button:banker.userId,userArr:userArr},game.roomInfo.roomId,true);
    recordGameAction(game,socket.resp.dingzhuang_all,{time:game.dingzhuangTime,button:banker.userId,userArr:userArr});
    setTimeout(function () {
        game.turnGamber = game.button;
        betting(game);
    },game.dingzhuangTime * 1000);

    // if(game.timeId1 <= 0)return;
    // game.timeId1 = -1;
    // var maxScore = 0;
    // var indexArr = [];
    // for (var i=0;i<game.gameSeats.length;i++){
    //     var ddd = game.gameSeats[i];
    //     if(!ddd || ddd.sit == 0)continue;
    //     if(ddd.score1 > maxScore){
    //         maxScore = ddd.score1;
    //         indexArr = [i];
    //     }
    //     else if(ddd.userId > 0 && ddd.score1 == maxScore){
    //         indexArr.push(i);
    //     }
    // }

    // if(indexArr.length == 1){
    //     game.button = indexArr[0];
    //     var sd = game.gameSeats[game.button];
    //     if(sd.score1 == 0){
    //         sd.score1 = 1;
    //         clientMgr.broadcastInRoom(socket.resp.qiangzhuang_notify,{userId:sd.userId,value:1},sd.userId,true);
    //         recordGameAction(game,socket.resp.qiangzhuang_notify,{userId:sd.userId,value:1});
    //     }
    //     xiazhu(game);
    // }
    // else{
    //     var random = Math.floor(Math.random()*indexArr.length);
    //     game.button = indexArr[random];
    //     var userArr = [];
    //     for(var i=0;i<indexArr.length;i++){
    //         var ddd = game.gameSeats[indexArr[i]];
    //         userArr.push(ddd.userId);
    //         if(ddd.score1 == 0) {
    //             clientMgr.broadcastInRoom(socket.resp.qiangzhuang_notify,{userId: ddd.userId,value: 0},ddd.userId, true);
    //             recordGameAction(game, socket.resp.qiangzhuang_notify, {userId: ddd.userId, value: 0});
    //         }
    //     }
    //     var sd = game.gameSeats[game.button];
    //     if(sd.score1 == 0){
    //         sd.score1 = 1;

    //     }
    //     game.state = game.allState.dingzhuang;
    //     clientMgr.broadcastInRoom2(socket.resp.dingzhuang_all,{time:game.dingzhuangTime,button:sd.userId,userArr:userArr},game.roomInfo.roomId,true);
    //     recordGameAction(game,socket.resp.dingzhuang_all,{time:game.dingzhuangTime,button:sd.userId,userArr:userArr});
    //     game.timeId2 = setTimeout(function () {
    //         xiazhu(game);
    //     },game.dingzhuangTime * 1000);
    // }
}

function getNextUserIndex(game, userSeatIndex) {
    for (var i = 1; i < game.gameSeats.length; ++i){
        var index = (i + userSeatIndex) % game.gameSeats.length;
        var user = game.gameSeats[index];
        if(!user || user.sit == 0)continue;
        if(user.userId > 0){
            return index;
        }
    }
}

function betting(game) {
    var userSeatIndex = game.turnGamber;
    var gambler = game.gameSeats[userSeatIndex];

    if(!gambler || gambler.sit == 0) {
        logger.game_log("下注阶段有人跑路了");
        return;
    }

    game.state = game.allState.xiazhu;
    var op = getOptionalOperate(game, userSeatIndex);
    logger.game_log("操作结果", op);
    var data = {time:game.xiazhuTime,gambler:gambler.userId,operates:op,fundPool:game.fundPool,beltCost:game.beltNowCost};
    clientMgr.broadcastInRoom2(socket.resp.dx_turn_betting_notify,data,game.roomInfo.roomId,true);
    // recordGameAction(game,socket.resp.dx_turn_betting_notify,{time:game.xiazhuTime,gambler:gambler.userId,operates:op});

    game.timerIdBetting = setTimeout(function () {
        // game.turnGamber = getNextUserIndex(game, game.turnGamber);
        // betting(game);
        exports.xiazhu(gambler.userId, 0);
    }, game.xiazhuTime * 1000);
}

function getOptionalOperate(game, userSeatIndex) {
    var gambler = game.gameSeats[userSeatIndex];
    logger.game_log("获取操作", game.button, userSeatIndex);
    if (game.isReverseBelt && gambler.scoreBetting > 0) {
        return DXOptionalOperate.REVERSE_BELT;
    }
    if (game.isOnlyEat) {
        if (game.bankerOnlyEat) {
            if (game.button == userSeatIndex) {
                return DXOptionalOperate.EAT;
            } else {
                return DXOptionalOperate.EAT_BELT;
            }
        } else {
            if (game.eatNoRub) {
                if (game.button == userSeatIndex) {
                    return DXOptionalOperate.EAT_TOUCH;
                } else {
                    return DXOptionalOperate.EAT_BELT;
                }
            } else {
                if (game.button == userSeatIndex) {
                    return DXOptionalOperate.EAT_TOUCH;
                } else {
                    return DXOptionalOperate.EAT_TOUCH_BELT;
                }
            }
        }
    } else {
        if (game.button == userSeatIndex) {
            return DXOptionalOperate.EAT_TOUCH;
        } else {
            return DXOptionalOperate.EAT_TOUCH_BELT;
        }
    }
}

// function xiazhu(game){
//     var sd = game.gameSeats[game.button];
//     var score1 = 1;
//     clientMgr.broadcastInRoom2(socket.resp.xiazhu_all,{time:game.xiazhuTime,button:sd.userId,beishu:score1},game.roomInfo.roomId,true);
//     recordGameAction(game,socket.resp.xiazhu_all,{time:game.xiazhuTime,button:sd.userId,beishu:score1});

//     game.state = game.allState.xiazhu;
//     game.timeId3 = setTimeout(function () {
//         cuopai(game);
//     },game.xiazhuTime * 1000);
// }
// function cuopai(game){
//     if(game.timeId3 <= 0)return;
//     game.timeId3 = -1;
//     for (var i=0;i<game.gameSeats.length;i++){
//         var ddd = game.gameSeats[i];
//         if(!ddd || ddd.sit == 0)continue;
//         if(ddd.score2 == 0  && i != game.button){
//             ddd.score2 = 2;
//             clientMgr.broadcastInRoom(socket.resp.xiazhu_notify,{userId:ddd.userId,value:2},ddd.userId,true);
//             recordGameAction(game,socket.resp.xiazhu_notify,{userId:ddd.userId,value:2});
//         }
//         var niu = calculate(ddd.holds);
//         clientMgr.sendMsg(ddd.userId, socket.resp.cuopai_all, {time:game.cuopaiTime,holds:ddd.holds,niu:niu});
//     }

//     game.state = game.allState.cuopai;
//     game.timeId4 = setTimeout(function () {
//         var turnSeat = game.gameSeats[game.button];
//         bipai(game,turnSeat.userId);
//     },game.cuopaiTime * 1000);
// }
function bipai(game){
    if(game.timeId4 <= 0)return;
    game.timeId4 = -1;

    for (var l=0;l<game.gameSeats.length;l++) {
        var gamber = game.gameSeats[l];
        if (!gamber) continue;
        if(gamber.hasLiang == false){
            gamber.cardType = getCardType(gamber.holds);
            clientMgr.broadcastInRoom(socket.resp.liangpai_notify, {userId: gamber.userId,holds: gamber.holds,sit:gamber.sit,cardType:gamber.cardType},gamber.userId,true);
            recordGameAction(game, socket.resp.liangpai_notify, {userId: gamber.userId,holds: gamber.holds,sit:gamber.sit,cardType:gamber.cardType});
        }
        clientMgr.sendMsg(gamber.userId, socket.resp.bipai_all, {time:game.liangpaiTime});
    }

    game.state = game.allState.bipai;
    game.timeId5 = setTimeout(function () {
        var banker = game.gameSeats[game.button];
        doGameOver(game,banker.userId);
    },game.liangpaiTime * 1000);
}

exports.qiangzhuang = function (userId,value) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.qiangzhuang)return;

    var gs = game.gameSeats[seatIndex];
    gs.score1 = value;
    gs.hasQiang = true;
    clientMgr.broadcastInRoom(socket.resp.qiangzhuang_notify,{userId:userId,value:value},userId,true);
    recordGameAction(game,socket.resp.qiangzhuang_notify,{userId:userId,value:value});

    var hasOver = true;
    for (var i=0;i<game.gameSeats.length;i++) {
        var ddd = game.gameSeats[i];
        if(!ddd || ddd.sit == 0)continue;
        if(ddd.hasQiang == false){
            hasOver = false;
        }
    }
    if(hasOver){
        dingzhuang(game);
    }
}
exports.rubCard = function (userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    game.gameSeats[seatIndex].hasRub = true;
}
exports.xiazhu = function (userId,value) {
    logger.game_log("用户下注", userId, value);
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.xiazhu)return;
    if (game.turnGamber != seatIndex) return;   // 不是轮到这个用户下注
    var gamber = roomInfo.seats[seatIndex];
    // gamber.score2 = value;
    // gamber.hasXia = true;
    logger.game_log("已有金币", gamber.coins, "打算下注", value);
    // if (value > gamber.coins) {
    //     logger.game_log("金币不足");
    //     recordGameAction(game,socket.resp.xiazhu_notify,{userId:userId,value:value,failed:1});
    //     return;
    // }
    if ((value > game.fundPool && game.beltNowCost != value) || value < 0) {
        logger.game_log("下注金额不正确");
        recordGameAction(game,socket.resp.xiazhu_notify,{userId:userId,value:value,failed:2});
        // return;
    }
    if (game.timerIdBetting != null) {
        clearTimeout(game.timerIdBetting);
        game.timerIdBetting = null;
    }
    
    var hasBetting = game.gameSeats[seatIndex].hasBetting;
    var op = DXOperate.WAIVE;
    if (game.turnGamber == game.button) {
        if (value == game.fundPool) {
            if (game.isOnlyEat && !game.gameSeats[seatIndex].hasRub) {
                op = DXOperate.ONLY_EAT;
            } else {
                op = DXOperate.EAT;
            }
        } else if (value == game.beltNowCost) {
            if (hasBetting) {
                op = DXOperate.REVERSE_BELT;
            } else {
                op = DXOperate.BELT;
            }
        } else if (value == 0) {
            if (hasBetting) {
                op = DXOperate.NO_BELT;
            } else {
                op = DXOperate.WAIVE;
            }
        } else {
            op = DXOperate.TOUCH;
        }
    } else {
        if (value == game.fundPool) {
            op = DXOperate.EAT;
        } else if (value == game.beltNowCost) {
            op = DXOperate.BELT;
        } else if (value == 0) {
            op = DXOperate.WAIVE;
        } else {
            op = DXOperate.TOUCH;
        }
    }
    if (!hasBetting && value == 0) {
        game.gameSeats[seatIndex].eliminate = true;
    }
    if (op == DXOperate.ONLY_EAT) {
        game.eatNoRub = true;
    }
    let over = false;
    if (game.gameSeats[seatIndex].hasBetting) {
        game.gameSeats[seatIndex].scoreReverse = value;
        over = true;
    }
    game.gameSeats[seatIndex].hasBetting = true;
    game.gameSeats[seatIndex].scoreBetting += value;
    game.beltNowCost += value;
    clientMgr.broadcastInRoom(socket.resp.xiazhu_notify,{userId:userId,value:value, op: op},userId,true);
    recordGameAction(game,socket.resp.xiazhu_notify,{userId:userId,value:value, op: op});

    // clientMgr.broadcastInRoom(socket.resp.gameoperate_notify,{userId:userId, op: op},userId,true);        
    //         recordGameAction(game,socket.resp.gameoperate_notify,{userId:userId, op: op});
    
    game.turnGamber = getNextUserIndex(game, game.turnGamber);

    if (game.isReverseBelt) {
        if (over) {
            bipai(game);
            return;
        }
        if (game.turnGamber == game.button) {
            if (game.gameSeats[game.button].eliminate) {
                bipai(game);
                return;
            }
            for (var i = 0; i < game.gameSeats.length; ++i){
                var user = game.gameSeats[i];
                if (!user || user.sit == 0) continue;
                if (game.turnGamber == i) continue;
                if (user.userId <= 0) continue;
                if (!user.eliminate) break;
            }
            if (i == game.gameSeats.length) {
                bipai(game);
                return;
            }
        }
    } else {
        if (game.button == game.turnGamber) { // 重新轮到头家
            bipai(game);
            return;
        }
    }
    if (game.beltNowCost == game.fundPool) {
        // 前面的都选择弃
        if (getNextUserIndex(game, game.turnGamber) == game.button) {
            game.gameSeats[game.turnGamber].scoreBetting = game.beltNowCost;
            bipai(game);
            return;
        }
    }
    betting(game);
}
exports.kanpai = function (userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.cuopai)return;

    clientMgr.broadcastInRoom(socket.resp.kanpai_notify,{userId:userId},userId,true);
    recordGameAction(game,socket.resp.kanpai_notify,{userId:userId});
}
exports.liangpai = function (userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.cuopai)return;

    var gs = game.gameSeats[seatIndex];
    if(gs.hasLiang)return;
    gs.hasLiang = true;

    var niu = calculate(gs.holds);
    clientMgr.broadcastInRoom(socket.resp.liangpai_notify,{userId:userId,holds: gs.holds,niu:niu,sit:gs.sit},userId,true);
    recordGameAction(game,socket.resp.liangpai_notify,{userId:userId,holds: gs.holds,niu:niu,sit:gs.sit});

    var hasOver = true;
    for (var i=0;i<game.gameSeats.length;i++) {
        var ddd = game.gameSeats[i];
        if(!ddd || ddd.sit == 0)continue;
        if(ddd.hasLiang == false){
            hasOver = false;
        }
    }
    if(hasOver){
        bipai(game,userId);
    }
}
function shuffle( game ) {
    let allCards = game.allCards;
    //初始化牌组
    for( let i = 2; i <= 12; i ++ ){
        if (i == 3) continue;
        allCards.push("" + i + CardDecor.HEART);
        allCards.push("" + i + CardDecor.BLOCK);
    }
    for( let i = 3; i <= 10; i ++ ){
        if (i == 5 || i == 9) continue;
        allCards.push("" + i + CardDecor.SPADE);
        if (i == 3) continue;
        allCards.push("" + i + CardDecor.PLUM);
    }
    allCards.push("" + 1 + 1);  // 大王-黑桃1
    //数组重新排序
	for( let i = 0; i < allCards.length; ++i ) {
		let lastIndex = allCards.length - 1 - i;
		let index = Math.floor( Math.random() * lastIndex );
		let t = allCards[ index ];
        allCards[ index ] = allCards[ lastIndex ];
        allCards[ lastIndex ] = t;
	}
}
function deal(game){
    //强制清0
    game.currentIndex = 0;

    var seatIndex = 0;
    for(var i = 0; i < 2 * game.gameSeats.length; ++i){
        if(game.gameSeats[seatIndex] == null){
            seatIndex ++;
            seatIndex %= game.gameSeats.length;
            continue;
        }
        var holds = game.gameSeats[seatIndex].holds;
        if(holds == null){
            holds = [];
            game.gameSeats[seatIndex].holds = holds;
        }
        mopai(game,seatIndex);
        seatIndex ++;
        seatIndex %= game.gameSeats.length;
    }
    for(var i = 0; i < game.gameSeats.length; ++i){
        if(game.gameSeats[i] == null){
            continue;
        }
        var holds = game.gameSeats[i].holds;
        logger.game_log(game.gameSeats[i].userId + " 摸到的牌为: " + holds);
    }
}
function mopai( game, seatIndex ) {
    if(game.currentIndex == game.allCards.length){
        return -1;
    }
    var data = game.gameSeats[seatIndex];
    var holds = data.holds;
    var pai = game.allCards[game.currentIndex];
    game.currentIndex ++;
    holds.push( pai );
    return pai;
}
// function createNiuniu( game ) {
//     var setNiuniu = false;
//     var index = -1;
//     for(var i = 0; i < game.gameSeats.length; ++i){
//         if(game.gameSeats[i] == null){
//             continue;
//         }
//         var seats = game.gameSeats[i];
//         if(seats.setNiuniu){
//             game.roomInfo.seats[i].setNiuniu = false;
//             setNiuniu = true;
//             index = i;
//         }
//     }

//     if(setNiuniu == false) return;
//     var maxIndex = -1;
//     var maxNiu = -1;
//     var maxNiuArr = [];
//     for(var i = 0; i < game.gameSeats.length; ++i) {
//         if (game.gameSeats[i] == null) {
//             continue;
//         }
//         var holds = game.gameSeats[i].holds;
//         var value = calculate(holds);
//         if(value > maxNiu){
//             maxNiu = value;
//             maxNiuArr = [i];
//         }
//         else if(value == maxNiu){
//             maxNiuArr.push(i);
//         }
//     }
//     if(maxNiuArr.length == 1){
//         maxIndex = maxNiuArr[0];
//     }
//     else{
//         var temp = maxNiuArr[0];
//         var seatData = game.gameSeats[temp];
//         for(var j = 1; j < maxNiuArr.length; ++j){
//             seatData = game.gameSeats[temp];
//             var sd = game.gameSeats[maxNiuArr[j]];
//             var result = compare(seatData.holds,sd.holds,maxNiu);
//             if(result < 0){
//                 temp = maxNiuArr[j];
//             }
//         }
//         maxIndex = temp;
//     }

//     var holds_temp = game.gameSeats[index].holds;
//     game.gameSeats[index].holds = game.gameSeats[maxIndex].holds;
//     game.gameSeats[maxIndex].holds = holds_temp;
// }

// function createNiuniu2( game ) {
//     var setNiuniu = false;
//     var index1 = -1;
//     var index2 = -1;
//     for(var i = 0; i < game.gameSeats.length; ++i){
//         if(game.gameSeats[i] == null){
//             continue;
//         }
//         var seats = game.gameSeats[i];
//         var rate = seats.setNiuniu2;
//         if(rate == 0)continue;
//         var rate2 = Math.abs(rate);
//         var randNum = Math.random() * 100;
//         logger.game_log("Control:",rate2,randNum);
//         if(randNum < rate2){
//             if(rate > 0) {
//                 index1 = i;
//             }
//             else{
//                 index2 = i;
//             }
//             setNiuniu = true;
//         }
//     }
//     if(setNiuniu == false) return;
//     var maxIndex = -1;
//     var maxNiu = -1;
//     var minIndex = 0;
//     var minNiu = 10;
//     var maxNiuArr = [];
//     for(var i = 0; i < game.gameSeats.length; ++i) {
//         if (game.gameSeats[i] == null) {
//             continue;
//         }
//         var holds = game.gameSeats[i].holds;
//         var value = calculate(holds);
//         if(value > maxNiu){
//             maxNiu = value;
//             maxNiuArr = [i];
//         }
//         else if(value == maxNiu){
//             maxNiuArr.push(i);
//         }
//         if(value < minNiu){
//             minNiu = value;
//             minIndex = i;
//         }
//     }
//     if(maxNiuArr.length == 1){
//         maxIndex = maxNiuArr[0];
//     }
//     else{
//         var temp = maxNiuArr[0];
//         var seatData = game.gameSeats[temp];
//         for(var j = 1; j < maxNiuArr.length; ++j){
//             seatData = game.gameSeats[temp];
//             var sd = game.gameSeats[maxNiuArr[j]];
//             var result = compare(seatData.holds,sd.holds,maxNiu);
//             if(result < 0){
//                 temp = maxNiuArr[j];
//             }
//         }
//         maxIndex = temp;
//     }

//     if(index1 > 0){
//         var holds_temp = game.gameSeats[index1].holds;
//         game.gameSeats[index1].holds = game.gameSeats[maxIndex].holds;
//         game.gameSeats[maxIndex].holds = holds_temp;
//     }
//     if(index2 > 0 && index2 != minIndex){
//         var holds_temp2 = game.gameSeats[index2].holds;
//         game.gameSeats[index2].holds = game.gameSeats[minIndex].holds;
//         game.gameSeats[minIndex].holds = holds_temp2;
//     }
// }

var CardDecor = {
    HEART: 2,   // 红桃
    BLOCK: 4,   // 方块
    SPADE: 1,   // 黑桃
    PLUM: 3,    // 梅花
    GHOST: 4,   // 鬼
}
// 获取花色
function getCardDecor(card) {
    return card % 10;
}

// 获取牌的值
function getCardValue(card) {
    return Math.floor(card / 10);
}

// 获取牌的点数
function getCardPoint(card) {
    if (isCard(card, 1, CardDecor.SPADE)) return 6;
    return Math.floor(card / 10);
}

function isRedCard(card) {
    var decor = getCardDecor(card);
    return decor == CardDecor.HEART || decor == CardDecor.BLOCK;
}

function isBlackCard(card) {
    var decor = getCardDecor(card);
    return decor == CardDecor.SPADE || decor == CardDecor.PLUM;
}

function isCard(card, targetCardValue, targetCardDecor) {
    if (getCardValue(card) != targetCardValue) return false;
    if (targetCardDecor != null) {
        if (getCardDecor(card) != targetCardDecor) return false;
    }
    return true;
}

function hasCard(cards, targetCardValue, targetCardDecor) {
    for (var i = 0; i < cards.length; ++i) {
        if (isCard(cards[i], targetCardValue, targetCardDecor)) {
            return true;
        }
    }
    return false;
}

// 是否是皇帝对
function isKingPair(cards) {
    // 钓蟹只有2张牌
    if (cards.length != 2) return false;
    if (cards[0] == cards[1]) return false;
    if (!hasCard(cards, 1, CardDecor.SPADE)) return false;
    if (!hasCard(cards, 3, CardDecor.SPADE)) return false;
    return true;
}

// 是否是对子
function isPair(cards) {
    if (cards.length != 2) return false;
    if (cards[0] == cards[1]) return false;
    if (getCardValue(cards[0]) != getCardValue(cards[1])) return false;
    if (isRedCard(cards[0]) && isRedCard(cards[1])) return true;
    if (isBlackCard(cards[0]) && isBlackCard(cards[1])) return true;
    return false;
}

// 天对
function isSkyPair(cards) {
    if (cards.length != 2) return false;
    if (!isPair(cards)) return false;
    return getCardValue(cards[0]) == 12;
}

// 地对
function isEarthPair(cards) {
    if (cards.length != 2) return false;
    if (!isPair(cards)) return false;
    return getCardValue(cards[0]) == 2;
}

// 人对
function isHumanPair(cards) {
    if (cards.length != 2) return false;
    if (!isPair(cards)) return false;
    if (!isRedCard(cards[0])) return false;
    return getCardValue(cards[0]) == 8;
}

// 鹅对/和对
function isGoosePair(cards) {
    if (cards.length != 2) return false;
    if (!isPair(cards)) return false;
    if (!isRedCard(cards[0])) return false;
    return getCardValue(cards[0]) == 4;
}

// 板凳对+梅花对+长三对
function isBenchPair(cards) {
    if (cards.length != 2) return false;
    if (!isPair(cards)) return false;
    if (!isBlackCard(cards[0])) return false;
    var cardValue = getCardValue(cards[0]);
    return cardValue == 4 || cardValue == 6 || cardValue == 10;
}

// 斧头对+红头对+霖六对+脚七对
function isAxePair(cards) {
    if (cards.length != 2) return false;
    if (!isPair(cards)) return false;
    if (!isRedCard(cards[0])) return false;
    var cardValue = getCardValue(cards[0]);
    return cardValue == 6 || cardValue == 7 || cardValue == 10 || cardValue == 11;
}

// 鸡仔对+红根对+风吹对
function isWindPair(cards) {
    if (cards.length != 2) return false;
    if (!isPair(cards)) return false;
    var cardValue = getCardValue(cards[0]);
    if (isRedCard(cards[0])) {
        return cardValue == 5 || cardValue == 9;
    } else {
        return cardValue == 7 || cardValue == 8;
    }
}

// 天九王
function isSkyNine(cards) {
    if (cards.length != 2) return false;
    if (getCardValue(cards[0]) == getCardValue(cards[1])) return false;
    if (!hasCard(cards, 12)) return false;
    if (!hasCard(cards, 9)) return false;
    return true;
}

// 地九王
function isEarthNine(cards) {
    if (cards.length != 2) return false;
    if (getCardValue(cards[0]) == getCardValue(cards[1])) return false;
    if (!hasCard(cards, 2)) return false;
    if (!hasCard(cards, 9)) return false;
    return true;
}

// 天杠
function isSkyBar(cards) {
    if (cards.length != 2) return false;
    if (getCardValue(cards[0]) == getCardValue(cards[1])) return false;
    if (!hasCard(cards, 12)) return false;
    if (!hasCard(cards, 8)) return false;
    return true;
}

// 地杠
function isEarthBar(cards) {
    if (cards.length != 2) return false;
    if (getCardValue(cards[0]) == getCardValue(cards[1])) return false;
    if (!hasCard(cards, 2)) return false;
    if (!hasCard(cards, 8)) return false;
    return true;
}

// 计算杂牌点数
function getMixCardPoint(cards) {
    if (cards.length != 2) return -1;
    var cardValue = getCardPoint(cards[0]) + getCardPoint(cards[1]);
    return cardValue % 10;
}

function calculate(cards) {
    if (isKingPair(cards)) return 1000;
    if (isSkyPair(cards)) return 990;
    if (isEarthPair(cards)) return 980;
    if (isHumanPair(cards)) return 970;
    if (isGoosePair(cards)) return 960;
    if (isBenchPair(cards)) return 950;
    if (isAxePair(cards)) return 940;
    if (isWindPair(cards)) return 930;
    if (isSkyNine(cards)) return 800;
    if (isEarthNine(cards)) return 790;
    if (isSkyBar(cards)) {
        return 750;
        // if (getCardValue(cards[0]) == 8) {
        //     if (isRedCard(cards[0])) {
        //         return 760;
        //     } else {
        //         return 750;
        //     }
        // } else {
        //     if (isRedCard(cards[1])) {
        //         return 760;
        //     } else {
        //         return 750;
        //     }
        // }
    }
    if (isEarthBar(cards)) {
        return 650;
        // if (getCardValue(cards[0]) == 8) {
        //     if (isRedCard(cards[0])) {
        //         return 660;
        //     } else {
        //         return 650;
        //     }
        // } else {
        //     if (isRedCard(cards[1])) {
        //         return 660;
        //     } else {
        //         return 650;
        //     }
        // }
    }
    var point = getMixCardPoint(cards);
    point = point * 10;
    if (hasCard(cards, 12)) {
        point = point + 9;
    } else if (hasCard(cards, 2)) {
        point = point + 8;
    } else if (hasCard(cards, 8, CardDecor.HEART) || hasCard(cards, 8, CardDecor.BLOCK)) {
        point = point + 7;
    } else if (hasCard(cards, 4, CardDecor.HEART) || hasCard(cards, 4, CardDecor.BLOCK)) {
        point = point + 6;
    } else if (hasCard(cards, 4, CardDecor.SPADE) || hasCard(cards, 4, CardDecor.PLUM)) {
        point = point + 5;
    } else if (hasCard(cards, 6, CardDecor.SPADE) || hasCard(cards, 6, CardDecor.PLUM)) {
        point = point + 5;
    } else if (hasCard(cards, 10, CardDecor.SPADE) || hasCard(cards, 10, CardDecor.PLUM)) {
        point = point + 5;
    } else if (hasCard(cards, 6, CardDecor.HEART) || hasCard(cards, 6, CardDecor.BLOCK)) {
        point = point + 3;
    } else if (hasCard(cards, 7, CardDecor.HEART) || hasCard(cards, 7, CardDecor.BLOCK)) {
        point = point + 3;
    } else if (hasCard(cards, 10, CardDecor.HEART) || hasCard(cards, 10, CardDecor.BLOCK)) {
        point = point + 3;
    } else if (hasCard(cards, 11)) {
        point = point + 3;
    } else if (hasCard(cards, 5)) {
        point = point + 1;
    } else if (hasCard(cards, 9)) {
        point = point + 1;
    } else if (hasCard(cards, 7, CardDecor.SPADE) || hasCard(cards, 7, CardDecor.PLUM)) {
        point = point + 1;
    } else if (hasCard(cards, 8, CardDecor.SPADE) || hasCard(cards, 8, CardDecor.PLUM)) {
        point = point + 1;
    }
    return point;
}

function getCardStringValue(hold) {
    var value = Math.floor(hold / 10);
    if(value == 10){
        return "X";
    }
    else if(value == 11){
        return "J";
    }
    else if(value == 12){
        return "Q";
    }
    else if(value == 13){
        return "K";
    }
    else{
        return "" + value;
    }
}

function getCardType(holds) {
    holds.sort(function(a, b) { return a - b });
    var name = "";
    for (let hold of holds) {
        name += getCardStringValue(hold);
    }
    let aRed = isRedCard(holds[0]);
    let bRed = isRedCard(holds[1]);
    let color = "m";
    if (aRed && bRed) {
        color = "r";
    } else if (!aRed && !bRed) {
        color = "b";
    }

    let aColor = aRed ? "r": "b";
    let bColor = bRed ? "r": "b";

    if (CARD_TYPE.indexOf(name + color) >= 0){
        return name + color;
    } else if (CARD_TYPE.indexOf(name) >= 0) {
        return name;
    } else if (CARD_TYPE.indexOf(aColor + name) >= 0) {
        return aColor + name;
    } else if (CARD_TYPE.indexOf(aColor + name.charAt(0) + bColor + name.charAt(1)) >= 0) {
        return aColor + name.charAt(0) + bColor + name.charAt(1);
    } else {
        return "dx_" + getMixCardPoint(holds);
    }
}
// function typeResult(point){
//     var beishu = 1;
//     if(point == 7 || point == 8){
//         beishu = 2;
//     }
//     else if(point == 9){
//         beishu = 3;
//     }
//     else if(point == 10){
//         beishu = 4;
//     }
//     else if(point > 10){
//         beishu = 5;
//     }
//     return beishu;
// }
// function compare(holds1,holds2,point){
//     //葫芦和炸弹特殊
//     if(point == 13 || point == 15){
//         var dict1 = {};
//         for (var i = 0; i < holds1.length; i++) {
//             var card = parseInt(holds1[i]);
//             var value = Math.floor(card / 10);
//             dict1[value] = dict1[value] === undefined ? 1 : dict1[value] + 1;
//         }
//         var hold1 = 0;
//         var count1 = 0;
//         for (var i in dict1) {
//             if(dict1[i] > count1){
//                 count1 = dict1[i];
//                 hold1 = i;
//             }
//         }
//         var dict2 = {};
//         for (var i = 0; i < holds2.length; i++) {
//             var card = parseInt(holds2[i]);
//             var value = Math.floor(card / 10);
//             dict2[value] = dict2[value] === undefined ? 1 : dict2[value] + 1;
//         }
//         var hold2 = 0;
//         var count2 = 0;
//         for (var i in dict2) {
//             if(dict2[i] > count2){
//                 count2 = dict2[i];
//                 hold2 = i;
//             }
//         }
//         return hold1 - hold2;
//     }
//     var maxType1 = 0;
//     var maxValue1 = 0;
//     var maxType2 = 0;
//     var maxValue2 = 0;
//     for(var i=0;i<holds1.length;i++){
//         var value = Math.floor(holds1[i] / 10);
//         var type = holds1[i] % 10;
//         if(value > maxValue1){
//             maxValue1 = value;
//             maxType1 = type;
//         }
//         else if(value == maxValue1 && type < maxType1){
//             maxType1 = type;
//         }
//     }
//     for(var i=0;i<holds2.length;i++){
//         var value = Math.floor(holds2[i] / 10);
//         var type = holds2[i] % 10;
//         if(value > maxValue2){
//             maxValue2 = value;
//             maxType2 = type;
//         }
//         else if(value == maxValue2 && type < maxType2){
//             maxType2 = type;
//         }
//     }
//     if(maxValue1 > maxValue2){
//         return 1;
//     }
//     else if(maxValue1 == maxValue2){
//         if(maxType1 < maxType2){
//             return 1;
//         }
//         else{
//             return -1;
//         }
//     }
//     else if(maxValue1 < maxValue2){
//         return -1;
//     }
// }
function calculateResult(game,roomInfo){
    var winner = null;
    var king = null;
    var winValue = 0;
    var totalLoseScore = 0;
    var mayBeLose = false;
    for (var i = 0; i < game.gameSeats.length; ++i) {
        var index = (i + game.button) % game.gameSeats.length;  // 从庄家开始轮
        var gamber = game.gameSeats[index];
        if (gamber == null || gamber.sit == 0) continue;
        var value = calculate(gamber.holds);
        if (value == 1000) king = gamber;        
        if (gamber.eliminate) continue;     // 玩家选择了弃
        // if (gamber.scoreBetting == 0) continue;     // 玩家选择了弃
        logger.game_log("玩家", gamber.userId, "的手牌是", gamber.holds, "得分是", value);
        if (winner == null || value > winValue) {
            winner = gamber;
            winValue = value;
            mayBeLose = false;
        } else if (value == winValue) {
            mayBeLose = true;
        }
        totalLoseScore += gamber.scoreBetting;
    }
    if (winner != game.gameSeats[game.button] || !winner.scoreReverse) {
        mayBeLose = false;
    }

    if (mayBeLose) {
        winner.scoreBetting -= winner.scoreReverse;
    }

    // if (winner.scoreBetting == 0) {
    //     winner.scoreBetting = game.fundPool;
    // }

    if (winner.scoreBetting >= game.fundPool) {
        for (var i = 0; i < game.gameSeats.length; ++i) {
            var gamber = game.gameSeats[i];
			var rs = roomInfo.seats[i];
            if (gamber == null || gamber.sit == 0) continue;
            if (!gamber.eliminate) continue;
            var value = calculate(gamber.holds);
            if (value > winValue) {
                rs.compensate = winner.scoreBetting;
                logger.game_log("赔底分数", rs.userId, rs.compensate);
            }
        }
    }
    // if (winner == null) {
    //     for (var i = 1; i < game.gameSeats.length; ++i) {
    //         var index = (game.gameSeats.length - i + game.button) % game.gameSeats.length;  // 从庄家开始轮
    //         var gamber = game.gameSeats[index];
    //         // logger.game_log("全弃:", gamber);
    //         if (gamber == null || gamber.sit == 0) continue;
    //         winner = gamber;
    //         winner.scoreBetting = game.fundPool;
    //         break;
    //     }
    // }
    totalLoseScore -= winner.scoreBetting;
    if (totalLoseScore > winner.scoreBetting) {
        // 多余的失分需要投入底池
        game.fundPool += totalLoseScore - winner.scoreBetting;
        
		for(var i = 0; i < roomInfo.seats.length; ++i){
			var sd = game.gameSeats[i];
			if( sd == null || sd.sit == 0 || sd.userId <= 0) continue;
            clientMgr.broadcastInRoom2(socket.resp.dizhu_cost,{fundPool:game.fundPool},roomInfo.roomId);
        }
    }

    if (totalLoseScore < winner.scoreBetting) {
        if (winner.scoreBetting > game.fundPool + totalLoseScore) {
            winner.scoreBetting = game.fundPool + totalLoseScore;
        }
        game.fundPool -= winner.scoreBetting - totalLoseScore;
        
		for(var i = 0; i < roomInfo.seats.length; ++i){
			var sd = game.gameSeats[i];
			if( sd == null || sd.sit == 0 || sd.userId <= 0) continue;
            clientMgr.broadcastInRoom2(socket.resp.dizhu_cost,{fundPool:game.fundPool},roomInfo.roomId);
        }
    }

    var people = 0;
    for (var i = 0; i < game.gameSeats.length; ++i) {
        var index = (i + game.button) % game.gameSeats.length;  // 从庄家开始轮
        var gamber = game.gameSeats[index];
        if (gamber == null || gamber.sit == 0) continue;
        people++;
        if (gamber.scoreBetting == 0) continue;     // 玩家选择了弃

        if (winner != gamber) {
            gamber.score -= gamber.scoreBetting;
        } else {
            gamber.score += gamber.scoreBetting;
            if (mayBeLose) {
                gamber.score -= gamber.scoreReverse;
                gamber.scoreBetting += gamber.scoreReverse;
            }
            // gamber.score = Math.min(gamber.scoreBetting, totalLoseScore);
        }
    }

    if (king) {  // 皇帝对
        for (var i = 0; i < game.gameSeats.length; ++i) {
            var gamber = game.gameSeats[i];
            if (gamber == null || gamber.sit == 0) continue;
            if (king != gamber) {
                gamber.score -= game.conf.difen * people;
            } else {
                gamber.score += game.conf.difen * people * (people - 1);
                logger.game_log("皇帝对得分", king.userId,people, game.conf.difen * people * (people - 1));
            }
        }
    }

    // var seatData = game.gameSeats[game.button];
    // var value = calculate(seatData.holds);
    // seatData.niu = value;
    // if(value >= 10)seatData.isNiuniu = true;
    // var beishu = typeResult(value);

	// for( var i=0; i < game.gameSeats.length; i++ ) {
    //     var sd = game.gameSeats[i];
    //     if(!sd || sd.sit == 0 || i == game.button)continue;
    //     var value2 = calculate(sd.holds);
    //     sd.niu = value2;
    //     if(value2 >= 10)sd.isNiuniu = true;
    //     if(value > value2){
    //         var score = seatData.score1 * sd.score2 * difen * beishu;
    //         seatData.score += score;
    //         sd.score -= score;
    //     }
    //     else if(value == value2){
    //         var result = compare(seatData.holds,sd.holds,value);
    //         if(result > 0){
    //             var score = seatData.score1 * sd.score2 * difen * beishu;
    //             seatData.score += score;
    //             sd.score -= score;
    //         }
    //         else if(result < 0){
    //             var beishu2 = typeResult(value2);
    //             var score = seatData.score1 * sd.score2 * difen * beishu2;
    //             seatData.score -= score;
    //             sd.score += score;
    //         }
    //     }
    //     else if(value < value2){
    //         var beishu2 = typeResult(value2);
    //         var score = seatData.score1 * sd.score2 * difen * beishu2;
    //         seatData.score -= score;
    //         sd.score += score;
    //     }
    // }
}

function doGameOver(game,userId,forceEnd){
    var roomId = roomMgr.getUserRoomId(userId);
    doGameOver2(game,roomId,forceEnd);
}
function doGameOver2(game,roomId,forceEnd){
	if(roomId == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
	roomInfo.gameState = "idle";
    clientMgr.broadcastInRoom2(socket.resp.game_state,{state:roomInfo.gameState},roomId);

	var results = [];
    var dbusers = [];
	var dbresult = [];
    var backcount = 0,renshu = 0;
    var isEnd = false;
    var endInfo = null;

	if(game != null){
	    if(!forceEnd){
			calculateResult(game,roomInfo);	
		}

        if(roomInfo.allRecord == null){
	        roomInfo.allRecord = [];
            roomInfo.allRecord[0] = {};
        }
        roomInfo.fundPool = game.fundPool;

        var record;
        if(roomInfo.conf.maxGames > 0){
            record = roomInfo.allRecord[roomInfo.numOfGames] = {};
        }
        else{
            record = roomInfo.allRecord = {};
        }
        var endTime = Date.now();
        var cost_coins = function (data,rs) {
            db.rate_coins(data,function (info) {
                var difen = game.conf.difen;
                logger.game_log(rs.userId, "目前金币为", info.coins, "目前底分为", difen);
                // if(info.coins <= difen){
                //     rs.sit = 0;
                //     rs.ready = 0;
                //     exports.sitDown(rs.userId,false);
                // }
                data.coins = info.coins;
                data.score = -1 * info.cost;
                record[data.userId].score = -1 * info.cost;
                backcount ++;

                //如果局数已够，则进行整体结算，并关闭房间
                if(backcount >= renshu){
                    logger.game_log("结算数据", record, game.fundPool);
                    clientMgr.broadcastInRoom2(socket.resp.game_over,{results:results,endInfo:endInfo,endTime:endTime,record:record},roomId);
                    if(isEnd){
                        logger.game_log("强制解散房间");
                        // clientMgr.broadcastInRoom2(socket.resp.dispress,"dispress",roomId);
                        clientMgr.kickAllInRoom(roomId);
                        roomMgr.destroy(roomId);
                    }
                }
            });
        }
		for(var i = 0; i < roomInfo.seats.length; ++i){
			var rs = roomInfo.seats[i];
			var sd = game.gameSeats[i];
            if(rs.shangzhuang == null){
                rs.shangzhuang = 0;
            }
            if(rs.niuniu == null){
                rs.niuniu = 0;
            }
            if(rs.win == null){
                rs.win = 0;
            }
			if( sd == null || sd.sit == 0 || sd.userId <= 0) continue;
            renshu ++;
            rs.shangzhuang += game.button == i?1:0;
            rs.niuniu += sd.isNiuniu?1:0;
            rs.win += sd.score > 0?1:0;

			rs.coins += sd.score;
            rs.score += sd.score;
            rs.ready = false;
            // rs.sit = 0;

            record[sd.userId] = {score:sd.score,holds:sd.holds,niu:sd.niu,isZhuang:game.button == i};

			var userRT = {
				userId:sd.userId,
                area : rs.area,
                coins:rs.coins,
                score:sd.score,
			};
			results.push(userRT);
            dbusers.push(sd.userId);
			dbresult.push(sd.score);
			sd.game = null;	//清除数据
			delete gameSeatsOfUsers[sd.userId];

            // logger.game_log("计算金币", userRT, rs);
            cost_coins(userRT,rs);
		}
		delete games[roomId];
	}
    var fnNoticeResult = function(isEnd){
        roomInfo.settle = roomInfo.settle || {};
        let check = game.fundPool;
        for(var i = 0; i < roomInfo.seats.length; ++i){
            var rs = roomInfo.seats[i];
            var sd = game.gameSeats[i];
            if(rs.userId <= 0 || (!sd || !sd.sit))continue;
            if(rs.shangzhuang == null){
                rs.shangzhuang = 0;
            }
            if(rs.niuniu == null){
                rs.niuniu = 0;
            }
            if(rs.win == null){
                rs.win = 0;
            }
            roomInfo.settle[rs.userId] = {
                userId:rs.userId,
                score:rs.score,
                shangzhuang:rs.shangzhuang,
                niuniu:rs.niuniu,
                win:rs.win,
            };
            check += rs.score;
        }
        if (check != 0) {
            logger.game_log("钓蟹分数结算有误", roomInfo.settle, game.fundPool);
        }
        if(isEnd){
            endInfo = [];
            for (let userId in roomInfo.settle) {
                endInfo.push(roomInfo.settle[userId]);
            }
        }

        if( isEnd ){
            if( roomInfo.numOfGames > 1) {
                store_history(game,roomInfo);
            }
        }
        else{
            setTimeout(function() {
                clearExit(roomInfo);
            }, 2000);

            // for(var i = 0; i < roomInfo.seats.length; ++i){
            //     var rs = roomInfo.seats[i];
            //     if(rs.userId <= 0)continue;
            //     if(!rs.ready) {
            //         exports.sitDown(r.userId, false);
            //     }
            // }

            logger.game_log("准备下一场游戏");
            clientMgr.broadcastInRoom2(socket.resp.next_all,{time:game.nextGameTime},roomId,true);
            recordGameAction(game,socket.resp.next_all,{time:game.nextGameTime});
            game.state = game.allState.idle;
            game.timeId5 = setTimeout(function () {
                var game = games[ roomId ];
                logger.game_log("准备新一轮游戏", game == null);
                if( game == null ) {
                    begin(roomId);
                }
            },game.nextGameTime * 1000);
        }
    }
	if(forceEnd || game == null){
        logger.game_log("游戏为空强制结束", game == null);
        isEnd = true;
		fnNoticeResult(true);
        clientMgr.broadcastInRoom2(socket.resp.dispress,"dispress",roomId);
        clientMgr.kickAllInRoom(roomId);
        roomMgr.destroy(roomId);
	}
	else{
        isEnd = isGameEnd(game, roomInfo);
        logger.game_log("游戏次数足够，结束游戏", roomInfo.numOfGames,roomInfo.conf.maxGames, isEnd);
        fnNoticeResult(isEnd);

        //记录打牌信息
        db.insert_game_records(roomId,roomInfo.type,roomInfo.createTime,roomInfo.numOfGames,dbusers,dbresult,game.actionList);
	}
}

function isGameEnd(game, roomInfo) {
    for(var i = 0; i < roomInfo.seats.length; ++i){
        var rs = roomInfo.seats[i];
        var sd = game.gameSeats[i];
        if( sd == null || sd.sit == 0 || sd.userId <= 0) continue;
        if (rs.compensate) {
            return false;
        }
    }
    return (roomInfo.numOfGames >= roomInfo.conf.maxGames && roomInfo.fundPool == 0) && roomInfo.conf.maxGames > 0;
}

function recordGameAction(game,cmd,result){
	game.actionList.push({cmd:cmd,result:result});
}

function store_history(game,roomInfo){
	var seats = roomInfo.seats;
	var history = {
		roomId:roomInfo.roomId,
        type : roomInfo.type,
        owner : roomInfo.owner,
        index : roomInfo.numOfGames,
		time:roomInfo.createTime,
        conf:roomInfo.conf,
        url : roomInfo.url,
		seats:[]
	};

	for(var i = 0; i < seats.length; ++i){
		var rs = seats[i];
		if(rs.userId <= 0){
		    continue;
        }
        var hs = history.seats[i] = {};
		hs.userId = rs.userId;
		hs.name = crypto.fromBase64(rs.userName);
		hs.score = rs.score;
	}
	db.store_history(history);
}

exports.hasBegan = function(roomId){
	var game = games[roomId];
    logger.game_log("pk_dx hasBegan", game == null, game == undefined);
	if(game && game.state != 0){
		return true;
	}
	// var roomInfo = roomMgr.getRoom(roomId);
	// if(roomInfo != null){
    //     return roomInfo.gameState == "playing";
	// 	// return roomInfo.numOfGames > 0;
	// }
	return false;
};

function updatePermission(userId) {
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "没有权限");
            return ;
        }
        
        clientMgr.sendMsg(userId, socket.resp.update_permission);
    });
}

exports.perspective = function(roomId, userId){
	var game = games[roomId];
	if(game == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "想要透视，没有权限");
            return ;
        }
        var seats = roomInfo.seats;
        var allHolds = [];
        for(var i = 0; i < seats.length; ++i) {
            if (!game.gameSeats[i]) continue;
            allHolds.push({userId:seats[i].userId,holds:game.gameSeats[i].holds});
        }
        logger.game_log("透视的牌", allHolds);
        clientMgr.sendMsg(userId, socket.resp.perspective, allHolds);
        recordGameAction(game,socket.resp.perspective,allHolds);
    });
};

exports.replaceCardGet = function(roomId, userId){
	var game = games[roomId];
	if(game == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "想要看牌堆，没有权限");
            return ;
        }
        var holds = [];
        for (var i = game.currentIndex; i < game.allCards.length; ++i) {
            holds.push(game.allCards[i]);
        }
        clientMgr.sendMsg(userId, socket.resp.replace_card_get, holds);
        recordGameAction(game,socket.resp.replace_card_get,holds);
    });
}

exports.replaceCardSet = function(roomId, userId, hold, target){
	var game = games[roomId];
	if(game == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
    
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "想要换牌，没有权限");
            return ;
        }
        
        var findCardIndex = function(cards, card, startIndex=0) {
            for (var i = startIndex; i < cards.length; ++i) {
                if (cards[i] == card) {
                    return i;
                }
            }
            return -1;
        }
        var cardIndex = findCardIndex(game.allCards, target, game.currentIndex);
        if (cardIndex == -1) {
            logger.game_log(userId, "要替换的目标牌不存在", hold, target);
            return;
        }

        var seatIndex = roomMgr.getUserIndex(userId);
        var holds = game.gameSeats[seatIndex].holds;
        var holdIndex = findCardIndex(holds, hold);
        if (holdIndex == -1) {
            logger.game_log(userId, "要替换的手牌不存在", hold, target);
            return;
        }
        holds[holdIndex] = target;
        game.allCards[cardIndex] = hold;
        
        clientMgr.sendMsg(userId, socket.resp.replace_card_set, holds);
        recordGameAction(game,socket.resp.replace_card_set, holds);
    });
}


function update() {
    for(var userId in kickList) {
        kickList[userId] -= 1;
        var roomId = roomMgr.getUserRoomId(userId);
        if(roomId == null){
            delete kickList[userId];
            continue;
        }
        var roomInfo = roomMgr.getRoom(roomId);
        if(roomInfo == null){
            delete kickList[userId];
            continue;
        }
        if(kickList[userId] < 0){
            clientMgr.sendMsg(userId,socket.resp.exit_result,userId);
            //通知其它玩家，有人退出了房间
            clientMgr.broadcastInRoom(socket.resp.exit_notify,userId,userId,false);
            roomMgr.exitRoom(userId);
            delete kickList[userId];
        }
    }
}
setInterval( update, 1000 );


